package com.tencent.bk.sdk.iam.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.tencent.bk.sdk.iam.config.IamConfiguration;
import com.tencent.bk.sdk.iam.dto.ExpressionWithResourceDTO;
import com.tencent.bk.sdk.iam.dto.InstanceDTO;
import com.tencent.bk.sdk.iam.dto.SubjectDTO;
import com.tencent.bk.sdk.iam.dto.action.ActionDTO;
import com.tencent.bk.sdk.iam.dto.action.ActionPolicyDTO;
import com.tencent.bk.sdk.iam.dto.expression.ExpressionDTO;
import com.tencent.bk.sdk.iam.dto.request.BatchQueryPolicyRequestDTO;
import com.tencent.bk.sdk.iam.dto.request.QueryPolicyRequestDTO;
import com.tencent.bk.sdk.iam.dto.request.QueryPolicyWithDependencyResourceRequestDTO;
import com.tencent.bk.sdk.iam.dto.resource.DependencyResourceInfoDTO;
import com.tencent.bk.sdk.iam.dto.resource.ResourceDTO;
import com.tencent.bk.sdk.iam.dto.response.QueryPolicyWithDependencyResourceResponseDTO;
import com.tencent.bk.sdk.iam.dto.response.ResponseDTO;
import com.tencent.bk.sdk.iam.service.HttpClientService;
import com.tencent.bk.sdk.iam.service.PolicyService;
import com.tencent.bk.sdk.iam.util.JsonUtil;
import com.tencent.bk.sdk.iam.util.ResponseUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PolicyServiceImpl implements PolicyService {
    private static final Logger log = LoggerFactory.getLogger(PolicyServiceImpl.class);
    private final IamConfiguration iamConfiguration;
    private final HttpClientService httpClientService;

    public PolicyServiceImpl(IamConfiguration iamConfiguration, HttpClientService httpClientService) {
        this.iamConfiguration = iamConfiguration;
        this.httpClientService = httpClientService;
    }

    public ExpressionDTO getPolicyByAction(String username, ActionDTO action, List<ResourceDTO> resourceList) {
        if (resourceList == null) {
            resourceList = Collections.emptyList();
        }

        QueryPolicyRequestDTO queryPolicyRequest = QueryPolicyRequestDTO.builder().subject(SubjectDTO.builder().id(username).type("user").build()).action(action).resourceList(resourceList).system(this.iamConfiguration.getSystemId()).build();
        if (log.isDebugEnabled()) {
            log.debug("Get policy by action request|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        }

        String policyResponse = this.httpClientService.doHttpPost("/api/v1/policy/query", queryPolicyRequest);
        if (StringUtils.isNotBlank(policyResponse)) {
            if (log.isDebugEnabled()) {
                log.debug("Get policy by action response|{}", policyResponse);
            }

            ResponseDTO responseInfo;
            try {
                responseInfo = (ResponseDTO) JsonUtil.fromJson(policyResponse, new TypeReference<ResponseDTO<ExpressionDTO>>() {
                });
            } catch (IOException var8) {
                log.error("Error while parse policy response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, policyResponse, var8});
                return null;
            }

            if (responseInfo != null) {
                ResponseUtil.checkResponse(responseInfo);
                return (ExpressionDTO)responseInfo.getData();
            }

            log.error("Get policy by action got empty response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        } else {
            log.error("Get policy by action got empty response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        }

        return null;
    }

    public ExpressionDTO getPolicyByActionForExtend(String username, ActionDTO action, List<ResourceDTO> resourceList) {
        if (resourceList == null) {
            resourceList = Collections.emptyList();
        }

        QueryPolicyRequestDTO queryPolicyRequest = QueryPolicyRequestDTO.builder().subject(SubjectDTO.builder().id(username).type("user").build()).action(action).resourceList(resourceList).system(this.iamConfiguration.getSystemId()).build();
        if (log.isDebugEnabled()) {
            log.debug("Get policy by action request|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        }

        String policyResponse = this.httpClientService.doHttpPost("/api/v1/policy/data_query", queryPolicyRequest);
        if (StringUtils.isNotBlank(policyResponse)) {
            if (log.isDebugEnabled()) {
                log.debug("Get policy by action response|{}", policyResponse);
            }

            ResponseDTO<ExpressionDTO> responseInfo;
            try {
                responseInfo = (ResponseDTO) JsonUtil.fromJson(policyResponse, new TypeReference<ResponseDTO<ExpressionDTO>>() {
                });
            } catch (IOException var8) {
                log.error("Error while parse policy response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, policyResponse, var8});
                return null;
            }

            if (responseInfo != null) {
                ResponseUtil.checkResponse(responseInfo);
                responseInfo.getData().setResult(responseInfo.getResult());
                return responseInfo.getData();
            }

            log.error("Get policy by action got empty response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        } else {
            log.error("Get policy by action got empty response!|{}|{}|{}|{}", new Object[]{username, action, resourceList, queryPolicyRequest});
        }

        return null;
    }

    public List<ActionPolicyDTO> batchGetPolicyByActionList(String username, List<ActionDTO> actionList, List<ResourceDTO> resourceList) {
        BatchQueryPolicyRequestDTO batchQueryPolicyRequest = BatchQueryPolicyRequestDTO.builder().subject(SubjectDTO.builder().id(username).type("user").build()).actionList(actionList).resourceList(resourceList).system(this.iamConfiguration.getSystemId()).build();
        if (log.isDebugEnabled()) {
            log.debug("Batch get policy by action list request|{}|{}|{}|{}", new Object[]{username, actionList, resourceList, batchQueryPolicyRequest});
        }

        String actionPolicyResponse = this.httpClientService.doHttpPost("/api/v1/policy/query_by_actions", batchQueryPolicyRequest);
        if (StringUtils.isNotBlank(actionPolicyResponse)) {
            if (log.isDebugEnabled()) {
                log.debug("Batch get policy by action list response|{}", actionPolicyResponse);
            }

            ResponseDTO responseInfo;
            try {
                responseInfo = (ResponseDTO)JsonUtil.fromJson(actionPolicyResponse, new TypeReference<ResponseDTO<List<ActionPolicyDTO>>>() {
                });
            } catch (IOException var8) {
                log.error("Error while parse action policy response!|{}|{}|{}|{}", new Object[]{username, actionList, resourceList, actionPolicyResponse, var8});
                return null;
            }

            if (responseInfo != null) {
                ResponseUtil.checkResponse(responseInfo);
                return (List)responseInfo.getData();
            }

            log.error("Batch get policy by action list got empty response!|{}|{}|{}|{}", new Object[]{username, actionList, resourceList, batchQueryPolicyRequest});
        } else {
            log.error("Batch get policy by action list got empty response!|{}|{}|{}|{}", new Object[]{username, actionList, resourceList, batchQueryPolicyRequest});
        }

        return null;
    }

    public ExpressionWithResourceDTO batchGetPolicyAndAttribute(String username, ActionDTO action, ResourceDTO selfResource, List<ResourceDTO> dependencyResource) {
        QueryPolicyWithDependencyResourceRequestDTO queryPolicyWithDependencyResourceRequest = new QueryPolicyWithDependencyResourceRequestDTO();
        queryPolicyWithDependencyResourceRequest.setSubject(SubjectDTO.builder().id(username).type("user").build());
        queryPolicyWithDependencyResourceRequest.setAction(action);
        if (selfResource != null) {
            queryPolicyWithDependencyResourceRequest.setResourceList(Collections.singletonList(selfResource));
        } else {
            queryPolicyWithDependencyResourceRequest.setResourceList(Collections.emptyList());
        }

        queryPolicyWithDependencyResourceRequest.setSystem(this.iamConfiguration.getSystemId());
        queryPolicyWithDependencyResourceRequest.setDependencyResource(dependencyResource);
        if (log.isDebugEnabled()) {
            log.debug("Batch get policy and attr request|{}|{}|{}|{}|{}", new Object[]{username, action, selfResource, dependencyResource, queryPolicyWithDependencyResourceRequest});
        }

        String policyAndResourceResponse = this.httpClientService.doHttpPost("/api/v1/policy/query_by_ext_resources", queryPolicyWithDependencyResourceRequest);
        if (StringUtils.isNotBlank(policyAndResourceResponse)) {
            if (log.isDebugEnabled()) {
                log.debug("Batch get policy and attr response|{}", policyAndResourceResponse);
            }

            ResponseDTO responseInfo;
            try {
                responseInfo = (ResponseDTO)JsonUtil.fromJson(policyAndResourceResponse, new TypeReference<ResponseDTO<QueryPolicyWithDependencyResourceResponseDTO>>() {
                });
            } catch (IOException var15) {
                log.error("Error while parse action policy response!|{}|{}|{}|{}|{}", new Object[]{username, action, selfResource, dependencyResource, policyAndResourceResponse, var15});
                return null;
            }

            if (responseInfo != null) {
                ResponseUtil.checkResponse(responseInfo);
                QueryPolicyWithDependencyResourceResponseDTO policyWithDependencyResource = (QueryPolicyWithDependencyResourceResponseDTO)responseInfo.getData();
                ExpressionWithResourceDTO expressionWithResource = new ExpressionWithResourceDTO();
                expressionWithResource.setExpression(policyWithDependencyResource.getExpression());
                List<DependencyResourceInfoDTO> dependencyResourceList = policyWithDependencyResource.getDependencyResourceList();
                Map<String, Map<String, List<InstanceDTO>>> instanceMap = new ConcurrentHashMap(dependencyResourceList.size());
                Iterator var12 = dependencyResourceList.iterator();

                while(var12.hasNext()) {
                    DependencyResourceInfoDTO dependencyResourceInfo = (DependencyResourceInfoDTO)var12.next();
                    if (StringUtils.isBlank(dependencyResourceInfo.getSystem())) {
                        log.error("Dependency resource should has system!");
                    } else if (dependencyResourceInfo.getInstanceList() == null) {
                        log.error("Null dependency resource instance list!");
                    } else {
                        Map<String, List<InstanceDTO>> typeResourceMap = (Map)instanceMap.computeIfAbsent(dependencyResourceInfo.getSystem(), (k) -> {
                            return new ConcurrentHashMap(dependencyResourceInfo.getInstanceList().size());
                        });
                        typeResourceMap.put(dependencyResourceInfo.getType(), dependencyResourceInfo.getInstanceList());
                    }
                }

                expressionWithResource.setInstanceMap(instanceMap);
                return expressionWithResource;
            }

            log.error("Empty response while batch get policy and attr!|{}|{}|{}|{}|{}", new Object[]{username, action, selfResource, dependencyResource, policyAndResourceResponse});
        } else {
            log.error("Empty response while batch get policy and attr!|{}|{}|{}|{}", new Object[]{username, action, selfResource, dependencyResource});
        }

        return null;
    }
}
